package com.twt.common.utils;

/**
 * @Desciption:
 * @ClassName:DateUtils
 * @Author:TwT
 * @Date:2022/6/25 9:35
 * @Version:1.0
 **/
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

public class DateUtils {
    private DateUtils() {
    }

    public static Date getCurrentDate() {
        return DateUtils.Convert.localDateTimeToDate(LocalDateTime.now());
    }

    public static String getCurrentDate(DateUtils.TimeFormat format) {
        return Objects.isNull(format) ? DateUtils.Const.EMPTY_STRING_OBJECT : format.formatter.format(LocalDateTime.now());
    }

    public static Timestamp getDateBefore(Timestamp t, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(t);
        now.set(5, now.get(5) - day);
        return new Timestamp(now.getTime().getTime());
    }

    public static Timestamp getDateAfter(Timestamp t, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(t);
        now.set(5, now.get(5) + day);
        return new Timestamp(now.getTime().getTime());
    }

    public static int daysBetween(Date sDate, Date bDate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            sDate = sdf.parse(sdf.format(sDate));
            bDate = sdf.parse(sdf.format(bDate));
            Calendar cal = Calendar.getInstance();
            cal.setTime(sDate);
            long time1 = cal.getTimeInMillis();
            cal.setTime(bDate);
            long time2 = cal.getTimeInMillis();
            long between_days = (time2 - time1) / 86400000L;
            return Integer.parseInt(String.valueOf(between_days));
        } catch (Exception var10) {
            var10.printStackTrace();
            return 0;
        }
    }

    public static Date getDate(int year, int month, int day, int hour, int minute, int second) {
        LocalDateTime localDateTime;
        try {
            localDateTime = LocalDateTime.of(year, month, day, hour, minute, second);
        } catch (Exception var8) {
            localDateTime = null;
        }

        return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_UTIL_DATE_OBJECT : DateUtils.Convert.localDateTimeToDate(localDateTime);
    }

    public static int getDaysOfMonth(Date date) {
        if (Objects.isNull(date)) {
            throw new NullPointerException();
        } else {
            LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            return getDaysOfMonth(localDateTime.getMonth().getValue(), localDateTime.getYear());
        }
    }

    public static int getDaysOfMonth(int month, int year) {
        if (month != 1 && month != 3 && month != 5 && month != 7 && month != 8 && month != 10 && month != 12) {
            if (month != 4 && month != 6 && month != 9 && month != 11) {
                return (year % 4 != 0 || year % 100 == 0) && year % 400 != 0 ? 28 : 29;
            } else {
                return 30;
            }
        } else {
            return 31;
        }
    }

    public static Date getFirstDayOfMonth(Date date) {
        return DateUtils.Convert.localDateTimeToDate(getFirstDayOfMonth(DateUtils.Convert.dateToLocalDateTime(date)));
    }

    public static Date getLastDayOfMonth(Date date) {
        return DateUtils.Convert.localDateTimeToDate(getLastDayOfMonth(DateUtils.Convert.dateToLocalDateTime(date)));
    }

    public static Date getFirstDayOfYear(Date date) {
        return DateUtils.Convert.localDateTimeToDate(getFirstDayOfYear(DateUtils.Convert.dateToLocalDateTime(date)));
    }

    public static Date getLastDayOfYear(Date date) {
        return DateUtils.Convert.localDateTimeToDate(getLastDayOfYear(DateUtils.Convert.dateToLocalDateTime(date)));
    }

    public static Date getFirstInMonth(Date date, DayOfWeek dayOfWeek) {
        return DateUtils.Convert.localDateTimeToDate(getFirstInMonth(DateUtils.Convert.dateToLocalDateTime(date), dayOfWeek));
    }

    public static Date getNext(Date date, DayOfWeek dayOfWeek) {
        return DateUtils.Convert.localDateTimeToDate(getNext(DateUtils.Convert.dateToLocalDateTime(date), dayOfWeek));
    }

    public static Date getPrevious(Date date, DayOfWeek dayOfWeek) {
        return DateUtils.Convert.localDateTimeToDate(getPrevious(DateUtils.Convert.dateToLocalDateTime(date), dayOfWeek));
    }

    public static LocalDateTime getFirstDayOfMonth(LocalDateTime date) {
        return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : date.with(TemporalAdjusters.firstDayOfMonth());
    }

    public static LocalDateTime getLastDayOfMonth(LocalDateTime date) {
        return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : date.with(TemporalAdjusters.lastDayOfMonth());
    }

    public static LocalDateTime getFirstDayOfYear(LocalDateTime date) {
        return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : date.with(TemporalAdjusters.firstDayOfYear());
    }

    public static LocalDateTime getLastDayOfYear(LocalDateTime date) {
        return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : date.with(TemporalAdjusters.lastDayOfYear());
    }

    public static LocalDateTime getFirstInMonth(LocalDateTime date, DayOfWeek dayOfWeek) {
        return !Objects.isNull(date) && !Objects.isNull(dayOfWeek) ? date.with(TemporalAdjusters.firstInMonth(dayOfWeek)) : DateUtils.Const.NULL_LOCALDATETIME_OBJECT;
    }

    public static LocalDateTime getNext(LocalDateTime date, DayOfWeek dayOfWeek) {
        return !Objects.isNull(date) && !Objects.isNull(dayOfWeek) ? date.with(TemporalAdjusters.next(dayOfWeek)) : DateUtils.Const.NULL_LOCALDATETIME_OBJECT;
    }

    public static LocalDateTime getPrevious(LocalDateTime date, DayOfWeek dayOfWeek) {
        return !Objects.isNull(date) && !Objects.isNull(dayOfWeek) ? date.with(TemporalAdjusters.previous(dayOfWeek)) : DateUtils.Const.NULL_LOCALDATETIME_OBJECT;
    }

    private static class InnerTools {
        private InnerTools() {
        }

        private static boolean isEmpty(CharSequence chs) {
            return Objects.isNull(chs) || chs.length() == 0;
        }
    }

    public static class TimeFormat {
        public static final DateUtils.TimeFormat HH_MM_SS_COLON = new DateUtils.TimeFormat("HH:mm:ss");
        public static final DateUtils.TimeFormat HH_MM_SS_MILSEC_COLON = new DateUtils.TimeFormat("HH:mm:ss.SSS");
        public static final DateUtils.TimeFormat HH_MM_SS_CHINESE = new DateUtils.TimeFormat("HH时mm分ss秒");
        public static final DateUtils.TimeFormat YYYY_MM_DD_CHINESE = new DateUtils.TimeFormat("yyyy年MM月dd日");
        public static final DateUtils.TimeFormat YYYY_MM_DD_LINE = new DateUtils.TimeFormat("yyyy-MM-dd");
        public static final DateUtils.TimeFormat YYYY_MM_DD_SLASH = new DateUtils.TimeFormat("yyyy/MM/dd");
        public static final DateUtils.TimeFormat YYYY_MM_DD_BACKSLASH = new DateUtils.TimeFormat("yyyy\\MM\\dd");
        public static final DateUtils.TimeFormat YYYY_MM_DD_NONE = new DateUtils.TimeFormat("yyyyMMdd");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_CHINESE = new DateUtils.TimeFormat("yyyy年MM月dd日 HH时mm分ss秒");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_LINE = new DateUtils.TimeFormat("yyyy-MM-dd HH:mm:ss");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_SLASH = new DateUtils.TimeFormat("yyyy/MM/dd HH:mm:ss");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_BACKSLASH = new DateUtils.TimeFormat("yyyy\\MM\\dd HH:mm:ss");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_NONE = new DateUtils.TimeFormat("yyyyMMdd HH:mm:ss");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_MILSEC_LINE = new DateUtils.TimeFormat("yyyy-MM-dd HH:mm:ss.SSS");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_MILSEC_SLASH = new DateUtils.TimeFormat("yyyy/MM/dd HH:mm:ss.SSS");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_MILSEC_BACKSLASH = new DateUtils.TimeFormat("yyyy\\MM\\dd HH:mm:ss.SSS");
        public static final DateUtils.TimeFormat YYYY_MM_DD_HH_MM_SS_MILSEC_NONE = new DateUtils.TimeFormat("yyyyMMdd HH:mm:ss.SSS");
        private DateTimeFormatter formatter;
        private String pattern;

        private TimeFormat(String pattern) {
            this.pattern = pattern;
            this.formatter = DateTimeFormatter.ofPattern(pattern);
        }

        public static DateUtils.TimeFormat getCustomPattern(String pattern) {
            return DateUtils.InnerTools.isEmpty(pattern) ? null : new DateUtils.TimeFormat(pattern);
        }

        public String getPattern() {
            return this.pattern;
        }
    }

    public static class ZoneConvert {
        private ZoneConvert() {
        }

        public static LocalDateTime getLocalDateTimeByZone(ZoneId zoneId) {
            return Objects.isNull(zoneId) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : LocalDateTime.now(zoneId);
        }

        public static LocalDate getLocalDateByZone(ZoneId zoneId) {
            return Objects.isNull(zoneId) ? DateUtils.Const.NULL_LOCALDATE_OBJECT : LocalDate.now(zoneId);
        }

        public static LocalTime getLocalTimeByZone(ZoneId zoneId) {
            return Objects.isNull(zoneId) ? DateUtils.Const.NULL_LOCALTIME_OBJECT : LocalTime.now(zoneId);
        }

        public static LocalDateTime getLocalDateTimeByZone(LocalDateTime localDateTime, ZoneId srcZoneId, ZoneId destZoneId) {
            if (!Objects.isNull(localDateTime) && !Objects.isNull(srcZoneId) && !Objects.isNull(destZoneId)) {
                ZoneOffset zoneOffset = localDateTime.atZone(destZoneId).getOffset();
                return localDateTime.atZone(srcZoneId).toInstant().atOffset(zoneOffset).toLocalDateTime();
            } else {
                return DateUtils.Const.NULL_LOCALDATETIME_OBJECT;
            }
        }

        public static LocalDate getLocalDateByZone(LocalDate localDate, ZoneId srcZoneId, ZoneId destZoneId) {
            return getLocalDateTimeByZone(localDate.atStartOfDay(), srcZoneId, destZoneId).toLocalDate();
        }

        public static LocalDateTime getLocalDateTimeByZone(LocalDateTime localDateTime, ZoneId zoneId) {
            return getLocalDateTimeByZone(localDateTime, ZoneId.systemDefault(), zoneId);
        }

        public static LocalDate getLocalDateByZone(LocalDate localDate, ZoneId zoneId) {
            return getLocalDateTimeByZone(localDate.atStartOfDay(), zoneId).toLocalDate();
        }

        public static Date getDateByZone(ZoneId zoneId) {
            return DateUtils.Convert.localDateTimeToDate(getLocalDateTimeByZone(zoneId));
        }

        public static Date getDateByZone(Date date, ZoneId zoneId) {
            return DateUtils.Convert.localDateTimeToDate(getLocalDateTimeByZone(DateUtils.Convert.dateToLocalDateTime(date), ZoneId.systemDefault(), zoneId));
        }

        public static Date getDateByZone(Date date, ZoneId srcZoneId, ZoneId destZoneId) {
            return DateUtils.Convert.localDateTimeToDate(getLocalDateTimeByZone(DateUtils.Convert.dateToLocalDateTime(date), srcZoneId, destZoneId));
        }
    }

    public static class Judge {
        private Judge() {
        }

        public static int compare(LocalDateTime first, LocalDateTime second) {
            return second.compareTo(first);
        }

        public static Duration intervalResultInDuration(LocalDateTime first, LocalDateTime second) {
            if (!Objects.isNull(first) && !Objects.isNull(second)) {
                return Duration.between(first, second);
            } else {
                throw new NullPointerException();
            }
        }

        public static Long intervalResultInMinute(LocalDateTime first, LocalDateTime second) {
            Duration duration = intervalResultInDuration(first, second);
            if (Objects.isNull(duration)) {
                throw new NullPointerException();
            } else {
                return duration.toMinutes();
            }
        }

        public static Long intervalResultInMill(LocalDateTime first, LocalDateTime second) {
            Duration duration = intervalResultInDuration(first, second);
            if (Objects.isNull(duration)) {
                throw new NullPointerException();
            } else {
                return duration.toMillis();
            }
        }

        public static Long intervalResultInHour(LocalDateTime first, LocalDateTime second) {
            Duration duration = intervalResultInDuration(first, second);
            if (Objects.isNull(duration)) {
                throw new NullPointerException();
            } else {
                return duration.toHours();
            }
        }

        public static Duration intervalResultInDuration(LocalTime first, LocalTime second) {
            return !Objects.isNull(first) && !Objects.isNull(second) ? Duration.between(first, second) : null;
        }

        public static Long intervalResultInHour(LocalTime first, LocalTime second) {
            Duration duration = intervalResultInDuration(first, second);
            if (Objects.isNull(duration)) {
                throw new NullPointerException();
            } else {
                return duration.toHours();
            }
        }

        public static Period intervalResultInPeriod(LocalDate first, LocalDate second) {
            if (!Objects.isNull(first) && !Objects.isNull(second)) {
                return Period.between(first, second);
            } else {
                throw new NullPointerException();
            }
        }

        public static int intervalResultInYear(LocalDate first, LocalDate second) {
            Period period = intervalResultInPeriod(first, second);
            if (Objects.isNull(period)) {
                throw new NullPointerException();
            } else {
                return period.getYears();
            }
        }

        public static int intervalResultInMonth(LocalDate first, LocalDate second) {
            Period period = intervalResultInPeriod(first, second);
            if (Objects.isNull(period)) {
                throw new NullPointerException();
            } else {
                return period.getYears() * 12 + period.getMonths();
            }
        }

        public static Long intervalResultInDay(LocalDate first, LocalDate second) {
            if (!Objects.isNull(first) && !Objects.isNull(second)) {
                return second.toEpochDay() - first.toEpochDay();
            } else {
                throw new NullPointerException();
            }
        }

        public static Long intervalResultInDay(LocalDateTime first, LocalDateTime second) {
            return intervalResultInDay(first.toLocalDate(), second.toLocalDate());
        }

        public static int intervalResultInYear(Date first, Date second) {
            return intervalResultInYear(DateUtils.Convert.dateToLocalDate(first), DateUtils.Convert.dateToLocalDate(second));
        }

        public static int intervalResultInYear(String firstDateStr, String secondDateStr, DateUtils.TimeFormat timeFormat) {
            return intervalResultInYear(DateUtils.Format.stringToLocalDate(firstDateStr, timeFormat), DateUtils.Format.stringToLocalDate(secondDateStr, timeFormat));
        }

        public static int intervalResultInYear(Timestamp first, Timestamp second) {
            return intervalResultInYear(DateUtils.Convert.timestampToLocalDate(first), DateUtils.Convert.timestampToLocalDate(second));
        }

        public static int intervalResultInYear(java.sql.Date first, java.sql.Date second) {
            return intervalResultInYear(DateUtils.Convert.sqlDateToLocalDate(first), DateUtils.Convert.sqlDateToLocalDate(second));
        }

        public static int intervalResultInMonth(Date first, Date second) {
            return intervalResultInMonth(DateUtils.Convert.dateToLocalDate(first), DateUtils.Convert.dateToLocalDate(second));
        }

        public static int intervalResultInMonth(Timestamp first, Timestamp second) {
            return intervalResultInMonth(DateUtils.Convert.timestampToLocalDate(first), DateUtils.Convert.timestampToLocalDate(second));
        }

        public static int intervalResultInMonth(java.sql.Date first, java.sql.Date second) {
            return intervalResultInMonth(DateUtils.Convert.sqlDateToLocalDate(first), DateUtils.Convert.sqlDateToLocalDate(second));
        }

        public static Long intervalResultInDay(Date first, Date second) {
            return intervalResultInDay(DateUtils.Convert.dateToLocalDate(first), DateUtils.Convert.dateToLocalDate(second));
        }

        public static Long intervalResultInDay(java.sql.Date first, java.sql.Date second) {
            return intervalResultInDay(DateUtils.Convert.sqlDateToLocalDate(first), DateUtils.Convert.sqlDateToLocalDate(second));
        }

        public static Long intervalResultInDay(Timestamp first, Timestamp second) {
            return intervalResultInDay(DateUtils.Convert.timestampToLocalDate(first), DateUtils.Convert.timestampToLocalDate(second));
        }

        public static Long intervalResultInHour(Time first, Time second) {
            return intervalResultInHour(DateUtils.Convert.sqlTimeToLocalTime(first), DateUtils.Convert.sqlTimeToLocalTime(second));
        }

        public static Long intervalResultInHour(String firstTimeStr, String secondTimeStr, DateUtils.TimeFormat timeFormat) {
            return intervalResultInHour(DateUtils.Format.stringToLocalTime(firstTimeStr, timeFormat), DateUtils.Format.stringToLocalTime(secondTimeStr, timeFormat));
        }

        public static Long intervalResultInHour(Timestamp first, Timestamp second) {
            return intervalResultInHour(DateUtils.Convert.timestampToLocalDateTime(first), DateUtils.Convert.timestampToLocalDateTime(second));
        }

        public static Long intervalResultInHour(Date first, Date second) {
            return intervalResultInHour(DateUtils.Convert.dateToLocalDateTime(first), DateUtils.Convert.dateToLocalDateTime(second));
        }

        public static Long intervalResultInMinute(Timestamp first, Timestamp second) {
            return intervalResultInMinute(DateUtils.Convert.timestampToLocalDateTime(first), DateUtils.Convert.timestampToLocalDateTime(second));
        }

        public static Long intervalResultInMinute(Date first, Date second) {
            return intervalResultInMinute(DateUtils.Convert.dateToLocalDateTime(first), DateUtils.Convert.dateToLocalDateTime(second));
        }

        public static Long intervalResultInMill(Timestamp first, Timestamp second) {
            return intervalResultInMill(DateUtils.Convert.timestampToLocalDateTime(first), DateUtils.Convert.timestampToLocalDateTime(second));
        }

        public static Long intervalResultInMill(Date first, Date second) {
            return intervalResultInMill(DateUtils.Convert.dateToLocalDateTime(first), DateUtils.Convert.dateToLocalDateTime(second));
        }
    }

    public static class Calculate {
        private Calculate() {
        }

        public static LocalDateTime localDateTimePlusCal(LocalDateTime localDateTime, int year, int month, int day, int hour, int minute, int second) {
            return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : localDateTime.plusYears((long) year).plusMonths((long) month).plusDays((long) day).plusHours((long) hour).plusMinutes((long) minute).plusSeconds((long) second);
        }

        public static LocalDateTime localDateTimePlusWeekCal(LocalDateTime localDateTime, int week) {
            return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : localDateTime.plusWeeks((long) week);
        }

        public static LocalDate localDatePlusCal(LocalDate localDate, int year, int month, int day) {
            return Objects.isNull(localDate) ? DateUtils.Const.NULL_LOCALDATE_OBJECT : localDate.plusYears((long) year).plusMonths((long) month).plusDays((long) day);
        }

        public static LocalDate localDatePlusWeekCal(LocalDate localDate, int week) {
            return Objects.isNull(localDate) ? DateUtils.Const.NULL_LOCALDATE_OBJECT : localDate.plusWeeks((long) week);
        }

        public static LocalTime localTimePlusCal(LocalTime localTime, int hour, int minute, int second) {
            return Objects.isNull(localTime) ? DateUtils.Const.NULL_LOCALTIME_OBJECT : localTime.plusHours((long) hour).plusMinutes((long) minute).plusSeconds((long) second);
        }

        public static Date datePlusCal(Date date, int year, int month, int day, int hour, int minute, int second) {
            return DateUtils.Convert.localDateTimeToDate(localDateTimePlusCal(DateUtils.Convert.dateToLocalDateTime(date), year, month, day, hour, minute, second));
        }

        public static Date datePlusWeekCal(Date date, int week) {
            return DateUtils.Convert.localDateTimeToDate(localDateTimePlusWeekCal(DateUtils.Convert.dateToLocalDateTime(date), week));
        }

        public static Timestamp timestampPlusCal(Timestamp timestamp, int year, int month, int day, int hour, int minute, int second) {
            return DateUtils.Convert.localDateTimeToTimestamp(localDateTimePlusCal(DateUtils.Convert.timestampToLocalDateTime(timestamp), year, month, day, hour, minute, second));
        }

        public static Timestamp timestampPlusWeekCal(Timestamp timestamp, int week) {
            return DateUtils.Convert.localDateTimeToTimestamp(localDateTimePlusWeekCal(DateUtils.Convert.timestampToLocalDateTime(timestamp), week));
        }

        public static java.sql.Date sqlDatePlusCal(java.sql.Date date, int year, int month, int day) {
            return DateUtils.Convert.localDateToSqlDate(localDatePlusCal(DateUtils.Convert.sqlDateToLocalDate(date), year, month, day));
        }

        public static java.sql.Date sqlDatePlusWeekCal(java.sql.Date date, int week) {
            return DateUtils.Convert.localDateToSqlDate(localDatePlusWeekCal(DateUtils.Convert.sqlDateToLocalDate(date), week));
        }

        public static Time sqlTimePlusCal(Time time, int hour, int minute, int second) {
            return DateUtils.Convert.localTimeToSqlTime(localTimePlusCal(DateUtils.Convert.sqlTimeToLocalTime(time), hour, minute, second));
        }
    }

    public static class Format {
        private Format() {
        }

        public static LocalDateTime stringToLocalDateTime(String dateStr, DateUtils.TimeFormat timeFormat) {
            return !DateUtils.InnerTools.isEmpty(dateStr) && !Objects.isNull(timeFormat) ? LocalDateTime.parse(dateStr, timeFormat.formatter) : DateUtils.Const.NULL_LOCALDATETIME_OBJECT;
        }

        public static LocalDateTime stringToLocalDateTime(String dateStr) {
            return stringToLocalDateTime(dateStr, DateUtils.Const.DEFAULT_DATETIME_FORMATTER);
        }

        public static LocalDate stringToLocalDate(String dateStr, DateUtils.TimeFormat timeFormat) {
            return !DateUtils.InnerTools.isEmpty(dateStr) && !Objects.isNull(timeFormat) ? LocalDate.parse(dateStr, timeFormat.formatter) : DateUtils.Const.NULL_LOCALDATE_OBJECT;
        }

        public static LocalDate stringToLocalDate(String dateStr) {
            return stringToLocalDate(dateStr, DateUtils.Const.DEFAULT_DATE_FORMATTER);
        }

        public static LocalTime stringToLocalTime(String dateStr, DateUtils.TimeFormat timeFormat) {
            return !DateUtils.InnerTools.isEmpty(dateStr) && !Objects.isNull(timeFormat) ? LocalTime.parse(dateStr, timeFormat.formatter) : DateUtils.Const.NULL_LOCALTIME_OBJECT;
        }

        public static LocalTime stringToLocalTime(String dateStr) {
            return stringToLocalTime(dateStr, DateUtils.Const.DEFAULT_TIME_FORMATTER);
        }

        public static Date stringToDate(String dateStr, DateUtils.TimeFormat timeFormat) {
            return DateUtils.Convert.localDateTimeToDate(stringToLocalDateTime(dateStr, timeFormat));
        }

        public static Date stringToDate(String dateStr) {
            return DateUtils.Convert.localDateTimeToDate(stringToLocalDateTime(dateStr));
        }

        public static java.sql.Date stringToSqlDate(String dateStr, DateUtils.TimeFormat timeFormat) {
            return DateUtils.Convert.localDateToSqlDate(stringToLocalDate(dateStr, timeFormat));
        }

        public static java.sql.Date stringToSqlDate(String dateStr) {
            return DateUtils.Convert.localDateToSqlDate(stringToLocalDate(dateStr));
        }

        public static Timestamp stringToTimestamp(String dateStr, DateUtils.TimeFormat timeFormat) {
            return DateUtils.Convert.localDateTimeToTimestamp(stringToLocalDateTime(dateStr, timeFormat));
        }

        public static Timestamp stringToTimestamp(String dateStr) {
            return DateUtils.Convert.localDateTimeToTimestamp(stringToLocalDateTime(dateStr));
        }

        public static Time stringToSqlTime(String dateStr, DateUtils.TimeFormat timeFormat) {
            return DateUtils.Convert.localTimeToSqlTime(stringToLocalTime(dateStr, timeFormat));
        }

        public static Time stringToSqlTime(String dateStr) {
            return DateUtils.Convert.localTimeToSqlTime(stringToLocalTime(dateStr));
        }

        public static String localDateTimeToString(LocalDateTime localDateTime, DateUtils.TimeFormat timeFormat) {
            return !Objects.isNull(localDateTime) && !Objects.isNull(timeFormat) ? timeFormat.formatter.format(localDateTime) : DateUtils.Const.EMPTY_STRING_OBJECT;
        }

        public static String localDateTimeToString(LocalDateTime localDateTime) {
            return localDateTimeToString(localDateTime, DateUtils.Const.DEFAULT_DATETIME_FORMATTER);
        }

        public static String localDateToString(LocalDate localDate, DateUtils.TimeFormat timeFormat) {
            return !Objects.isNull(localDate) && !Objects.isNull(timeFormat) ? timeFormat.formatter.format(localDate) : DateUtils.Const.EMPTY_STRING_OBJECT;
        }

        public static String localDateToString(LocalDate localDate) {
            return localDateToString(localDate, DateUtils.Const.DEFAULT_DATE_FORMATTER);
        }

        public static String localTimeToString(LocalTime localTime, DateUtils.TimeFormat timeFormat) {
            return !Objects.isNull(localTime) && !Objects.isNull(timeFormat) ? timeFormat.formatter.format(localTime) : DateUtils.Const.EMPTY_STRING_OBJECT;
        }

        public static String localTimeToString(LocalTime localTime) {
            return localTimeToString(localTime, DateUtils.Const.DEFAULT_TIME_FORMATTER);
        }

        public static String dateToString(Date date, DateUtils.TimeFormat timeFormat) {
            return localDateTimeToString(DateUtils.Convert.dateToLocalDateTime(date), timeFormat);
        }

        public static String dateToString(Date date) {
            return dateToString(date, DateUtils.Const.DEFAULT_DATETIME_FORMATTER);
        }

        public static String timestampToString(Timestamp timestamp, DateUtils.TimeFormat timeFormat) {
            return localDateTimeToString(DateUtils.Convert.timestampToLocalDateTime(timestamp), timeFormat);
        }

        public static String timestampToString(Timestamp timestamp) {
            return timestampToString(timestamp, DateUtils.Const.DEFAULT_DATETIME_FORMATTER);
        }

        public static String sqlTimeToString(Time time, DateUtils.TimeFormat timeFormat) {
            return localTimeToString(DateUtils.Convert.sqlTimeToLocalTime(time), timeFormat);
        }

        public static String sqlTimeToString(Time time) {
            return sqlTimeToString(time, DateUtils.Const.DEFAULT_TIME_FORMATTER);
        }

        public static String sqlDateToString(java.sql.Date date, DateUtils.TimeFormat timeFormat) {
            return localDateToString(DateUtils.Convert.sqlDateToLocalDate(date), timeFormat);
        }

        public static String sqlDateToString(java.sql.Date date) {
            return sqlDateToString(date, DateUtils.Const.DEFAULT_DATE_FORMATTER);
        }
    }

    public static class Convert {
        private Convert() {
        }

        public static Date localDateTimeToDate(LocalDateTime localDateTime) {
            return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_UTIL_DATE_OBJECT : Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        }

        public static Date localDateToDate(LocalDate localDate) {
            return Objects.isNull(localDate) ? DateUtils.Const.NULL_UTIL_DATE_OBJECT : Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
        }

        public static Date localTimeToDate(LocalTime localTime) {
            return Objects.isNull(localTime) ? DateUtils.Const.NULL_UTIL_DATE_OBJECT : localDateTimeToDate(localTime.atDate(LocalDate.now()));
        }

        public static LocalTime dateToLocalTime(Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALTIME_OBJECT : date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
        }

        public static LocalDate dateToLocalDate(Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATE_OBJECT : date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }

        public static LocalDateTime dateToLocalDateTime(Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        }

        public static Timestamp localDateTimeToTimestamp(LocalDateTime localDateTime) {
            return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_SQL_TIMESTAMP_OBJECT : Timestamp.valueOf(localDateTime);
        }

        public static Timestamp localDateToTimestamp(LocalDate localDate) {
            return Objects.isNull(localDate) ? DateUtils.Const.NULL_SQL_TIMESTAMP_OBJECT : Timestamp.valueOf(localDate.atStartOfDay());
        }

        public static Timestamp localTimeToTimestamp(LocalTime localTime) {
            return Objects.isNull(localTime) ? DateUtils.Const.NULL_SQL_TIMESTAMP_OBJECT : Timestamp.valueOf(localTime.atDate(LocalDate.now()));
        }

        public static LocalTime timestampToLocalTime(Timestamp timestamp) {
            return Objects.isNull(timestamp) ? DateUtils.Const.NULL_LOCALTIME_OBJECT : timestamp.toLocalDateTime().toLocalTime();
        }

        public static LocalDate timestampToLocalDate(Timestamp timestamp) {
            return Objects.isNull(timestamp) ? DateUtils.Const.NULL_LOCALDATE_OBJECT : timestamp.toLocalDateTime().toLocalDate();
        }

        public static LocalDateTime timestampToLocalDateTime(Timestamp timestamp) {
            return Objects.isNull(timestamp) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : timestamp.toLocalDateTime();
        }

        public static java.sql.Date localDateTimeToSqlDate(LocalDateTime localDateTime) {
            return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_SQL_DATE_OBJECT : java.sql.Date.valueOf(localDateTime.toLocalDate());
        }

        public static java.sql.Date localDateToSqlDate(LocalDate localDate) {
            return Objects.isNull(localDate) ? DateUtils.Const.NULL_SQL_DATE_OBJECT : java.sql.Date.valueOf(localDate);
        }

        public static LocalDate sqlDateToLocalDate(java.sql.Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATE_OBJECT : date.toLocalDate();
        }

        public static LocalDateTime sqlDateToLocalDateTime(java.sql.Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : date.toLocalDate().atStartOfDay();
        }

        public static Time localDateTimeToSqlTime(LocalDateTime localDateTime) {
            return Objects.isNull(localDateTime) ? DateUtils.Const.NULL_SQL_TIME_OBJECT : Time.valueOf(localDateTime.toLocalTime());
        }

        public static Time localTimeToSqlTime(LocalTime localTime) {
            return Objects.isNull(localTime) ? DateUtils.Const.NULL_SQL_TIME_OBJECT : Time.valueOf(localTime);
        }

        public static LocalTime sqlTimeToLocalTime(Time time) {
            return Objects.isNull(time) ? DateUtils.Const.NULL_LOCALTIME_OBJECT : time.toLocalTime();
        }

        public static LocalDateTime sqlTimeToLocalDateTime(Time time) {
            return Objects.isNull(time) ? DateUtils.Const.NULL_LOCALDATETIME_OBJECT : time.toLocalTime().atDate(LocalDate.now());
        }

        public static Time dateToSqlTime(Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_SQL_TIME_OBJECT : new Time(date.getTime());
        }

        public static Timestamp dateToTimestamp(Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_SQL_TIMESTAMP_OBJECT : new Timestamp(date.getTime());
        }

        public static java.sql.Date dateToSqlDate(Date date) {
            return Objects.isNull(date) ? DateUtils.Const.NULL_SQL_DATE_OBJECT : new java.sql.Date(date.getTime());
        }
    }

    private static class Const {
        private static final Date NULL_UTIL_DATE_OBJECT = null;
        private static final Timestamp NULL_SQL_TIMESTAMP_OBJECT = null;
        private static final java.sql.Date NULL_SQL_DATE_OBJECT = null;
        private static final Time NULL_SQL_TIME_OBJECT = null;
        private static final LocalDateTime NULL_LOCALDATETIME_OBJECT = null;
        private static final LocalDate NULL_LOCALDATE_OBJECT = null;
        private static final LocalTime NULL_LOCALTIME_OBJECT = null;
        private static final String EMPTY_STRING_OBJECT = null;
        private static final DateUtils.TimeFormat DEFAULT_DATETIME_FORMATTER;
        private static final DateUtils.TimeFormat DEFAULT_DATE_FORMATTER;
        private static final DateUtils.TimeFormat DEFAULT_TIME_FORMATTER;

        private Const() {
        }

        static {
            DEFAULT_DATETIME_FORMATTER = DateUtils.TimeFormat.YYYY_MM_DD_HH_MM_SS_LINE;
            DEFAULT_DATE_FORMATTER = DateUtils.TimeFormat.YYYY_MM_DD_LINE;
            DEFAULT_TIME_FORMATTER = DateUtils.TimeFormat.HH_MM_SS_COLON;
        }
    }

    public static enum Zone {
        CTT("Asia/Shanghai"),
        ART("Africa/Cairo"),
        CNT("America/St_Johns"),
        PRT("America/Puerto_Rico"),
        PNT("America/Phoenix"),
        PLT("Asia/Karachi"),
        AST("America/Anchorage"),
        BST("Asia/Dhaka"),
        CST("America/Chicago"),
        EST("-05:00"),
        HST("-10:00"),
        JST("Asia/Tokyo"),
        IST("Asia/Kolkata"),
        AGT("America/Argentina/Buenos_Aires"),
        NST("Pacific/Auckland"),
        MST("-07:00"),
        AET("Australia/Sydney"),
        BET("America/Sao_Paulo"),
        PST("America/Los_Angeles"),
        ACT("Australia/Darwin"),
        SST("Pacific/Guadalcanal"),
        VST("Asia/Ho_Chi_Minh"),
        CAT("Africa/Harare"),
        ECT("Europe/Paris"),
        EAT("Africa/Addis_Ababa"),
        IET("America/Indiana/Indianapolis"),
        MIT("Pacific/Apia"),
        NET("Asia/Yerevan");

        private transient ZoneId zoneId;

        private Zone(String zoneId) {
            this.zoneId = ZoneId.of(zoneId);
        }

        public ZoneId getZoneId() {
            return this.zoneId;
        }
    }
}
